/* Dancing Links DLX精确覆盖问题
* 1.DS 十字链表


* 2.题型
    1.精确覆盖问题
    2.配合覆盖问题(配合IDA*)

* 3.优化
    找到一个含 1 最少的列，然后再该列中枚举选择哪一行，
    如果选择某一行，则其他行应该删除，因为精确覆盖每一列有且只有一个 1，
    另外对于选择的行，其中出现 1 的列也应该删除，
    另外需要注意的一点：删除列时对于真正节点只需要在上下方向删除，
    因为后面对于某含最少个数的 1 的列，通过上下指针枚举行，
    而那些要删除的行我们已经在上下方向删除了不会被枚举到，恢复时反向也好恢复
*/

#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;
#define DEBUG
inline int read()
{
	int x=0;char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x;
}
inline void write(int x)
{
	if (x>=10) write(x/10);
	putchar(x%10+48);
}//快读快输

const int N=32010, INF=0x3f3f3f3f;
char block[12][4][5] = {
    {
        "**",
        "* "
    },
    {
        "****",
        "    ",
        "    ",
        "    "
    },
    {
        "***",
        "*  ",
        "   "
    },
    {
        "**",
        "**"
    },
    {
        "*  ",
        "*  ",
        "***"
    },
    {
        "****",
        " *  ",
        "    ",
        "    "
    },
    {
        "***",
        "* *",
        "   "
    },
    {
        "***",
        "** ",
        "   "
    },
    {
        "*** ",
        "  **",
        "    ",
        "    "
    },
    {
        " * ",
        "***",
        " * "
    },
    {
        "*  ",
        "** ",
        " **"
    },
    {
        "****",
        "*   ",
        "    ",
        "    "
    }
}; //用正方形字符矩阵表示所有零件


int n, m=67;
int l[N], r[N], u[N], d[N], s[N], row[N], col[N], idx; 
//左右上下指针            每列1的数量 每个节点所在行，列 节点编号
int ans[N], top; //最终选择行 ans指针

int id[10][10]; //(x, y)所在格子编号
vector<vector<vector<int>>> sol; //存储十字链表中每一行对应的零件状态，每个状态中存储它所有点的坐标
char chr[N]; //chr[i] 表示 sol[i] 中对应零件的类型
set<vector<vector<int>>> S; //存储零件通过翻转、旋转得到的所有形状
char g[20][20]; //存储原图

void rev1(char str[4][5]) //左右反转
{
    int len = strlen(str[0]);
    for(int i = 0, j = len - 1; i < j; i++, j--)
        for(int k = 0; k < len; k++)
            swap(str[i][k], str[j][k]);
}

void rev2(char str[4][5]) //斜反转
{
    int len = strlen(str[0]);
    for(int i = 0; i < len; i++)
        for(int j = 0; j < i; j++)
            swap(str[i][j], str[j][i]);
}

//str[4][5] 表示字符串矩阵
//(a, b) 表示字符串矩阵左上角的位置（偏移量）
vector<vector<int>> get(char str[4][5], int a, int b) //找出当前零件占了的所有位置的坐标
{
    vector<vector<int>> res;
    for(int i=0; i<4; i++)
        for(int j=0; j<4; j++)
            if(str[i][j]=='*')
                res.push_back({i+a, j+b});
    return res;
}

//str[4][5] 表示字符串矩阵
//(a, b) 表示字符串矩阵左上角的位置（偏移量）
//c 表示当前字符串矩阵的类型
bool check(char str[4][5], int c, int a, int b) //判断当前零件的状态是否合法
{
    auto A=get(str, a, b);
    vector<vector<int>> B; //原图所有类型为c的位置
    for(int i=0; i<10; i++)
        for(int j=0; j<=i; j++)
            if(g[i][j]==c+'A') 
                B.push_back({i, j});

    if(B.size()) //原图已经有c，查重(判断一下当前零件和原图中的零件能否对应上)
    {
        sort(A.begin(), A.end()), sort(B.begin(), B.end());
        return A==B; //完全一样->合法
    }

    //原图没有，需要判断位置是否合法
    for(int i=0; i<A.size(); i++)
    {
        int x=A[i][0], y=A[i][1];
        if(x<0 || x>=10 || y<0 || y>=10) return false; //越界
        if(g[x][y]!='.') return false; //冲突
    }
    return true;
}

void init() //初始化循环链表指针
{
    for(int i=0; i<=m; i++)
    {
        l[i]=i-1, r[i]=i+1;
        u[i]=d[i]=i; //只有一行，上下指针指向自己
    }
    l[0]=m, r[m]=0; //左右边界
    idx=m+1;
}

//添加节点(x, y) 列头(->idx(x,y)->...
void add(int &hh, int &tt, int x, int y) //行的头尾节点索引 新节点的位置 y是列号，也是这个列链表的头节点
{
    row[idx]=x, col[idx]=y, s[y]++; //记录当前节点位置(设置为横向，纵向的列头) 更新
    u[idx]=y, d[idx]=d[y], u[d[y]]=idx, d[y]=idx; //插入列y纵向链表 y->idx->...
    //新节点的上个节点是队头y 新节点的下个节点是原队头的下个节点 原下个节点的上个节点是新节点
    r[hh]=l[tt]=idx, r[idx]=tt, l[idx]=hh, tt=idx++; //横向链表队尾
} 

void remove(int pos) //删除pos列
{
    r[l[pos]]=r[pos], l[r[pos]]=l[pos]; //列头节点从横向链表删除
    for(int i=d[pos]; i!=pos; i=d[i]) //pos列是1的所有行删除
        for(int j=r[i]; j!=i; j=r[j]) //i所在行更新
        {
            s[col[j]]--;
            u[d[j]]=u[j], d[u[j]]=d[j]; //纵向删除
        }
}

void resume(int pos) //恢复pos列 与remove逆操作，访问顺序相反
{
    for(int i=u[pos]; i!=pos; i=u[i])
        for(int j=l[i]; j!=i; j=l[j])
        {
            u[d[j]]=j, d[u[j]]=j;
            s[col[j]]++;
        }
    r[l[pos]]=pos, l[r[pos]]=pos;
}

bool dfs()
{
    if(!r[0]) return true; //所有行已删除
    //找到1的个数最少的列
    int pos=r[0];
    for(int i=r[0]; i; i=r[i])
        if(s[i]<s[pos])
            pos=i;

    remove(pos); //删除这一列
    for(int i=d[pos]; i!=pos; i=d[i]) //枚举当前选择行
    {
        ans[++top]=row[i];
        for(int j=r[i]; j!=i; j=r[j]) remove(col[j]); //当前行中的其他1所在列删除
        if(dfs()) return true;
        //无解，恢复现场
        for(int j=l[i]; j!=i; j=l[j]) resume(col[j]); //恢复当前行
        top--;
    }
    resume(pos);
    return false;
}

signed solve()
{
    for(int i=0, k=1; i<10; i++)
        for(int j=0; j<=i; j++, k++)
            id[i][j]=k;
    for(int i=0; i<10; i++) scanf("%s", g[i]);

    init();
    for(int i=0; i<12; i++)
        for(int u=0; u<2; u++) //翻转
        {
            for(int j=0; j<4; j++) //旋转
            {
                for(int a=-10; a<10; a++) //平移
                    for(int b=-10; b<10; b++)
                        if(check(block[i], i, a, b))
                        {
                            auto t=get(block[i], a, b); //找出当前零件占了的所有位置的坐标
                            if(S.count(t)) continue; //已存在
                            //新状态 需要加入
                            int hh=idx, tt=idx;
                            for(int v=0; v<t.size(); v++)
                            {
                                int x=t[v][0], y=t[v][1];
                                add(hh, tt, sol.size(), id[x][y]); //限制1:每个格子只能放1个零件
                            }
                            add(hh, tt, sol.size(), 55+i+1); //限制 2：每个零件只能有1次

                            chr[sol.size()]='A'+i;
                            sol.push_back(t); //当前行对应的零件状态加入
                            S.insert(t); //当前状态加入
                        }
                //逆时针 90 度旋转
                rev1(block[i]);
                rev2(block[i]);
            }
            rev1(block[i]); //左右翻转
        }

    if(dfs())
    {
        for(int i=1; i<=top; i++)
        {
            auto &points=sol[ans[i]];
            char z=chr[ans[i]];
            for(int j=0; j<points.size(); j++)
            {
                int x=points[j][0], y=points[j][1];
                g[x][y]=z;
            }
        }
        for(int i = 0; i < 10; i++) puts(g[i]);
    }
    else
        puts("No solution");
    return 0;
}


signed main()
{
    #ifdef DEBUG
        freopen("./in.txt","r",stdin);
        freopen("./out.txt","w",stdout);
    #endif

    
    int T=1; //T=read();
    while(T--)
    {
        solve();
    }
    return 0;
}